package io.kiki.stack.netty.serialization;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.SerializerFactory;
import io.kiki.stack.netty.exception.CodecException;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

@Slf4j
@Setter
@Getter
public class HessianSerializer implements Serializer {

    private static final ThreadLocal<ByteArrayOutputStream> localOutputByteArray = ThreadLocal.withInitial(ByteArrayOutputStream::new);
    private final SerializerFactory serializerFactory = new SerializerFactory();


    @Override
    public byte[] serialize(Object object) throws CodecException {
        ByteArrayOutputStream byteArrayOutputStream = localOutputByteArray.get();
        byteArrayOutputStream.reset();
        Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
        hessian2Output.setSerializerFactory(serializerFactory);
        try {
            hessian2Output.writeObject(object);
            hessian2Output.close();
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new CodecException("IOException occurred when Hessian serializer encode!", e);
        }

    }


    @Override
    public <T> T deserialize(byte[] bytes, String className) throws CodecException {
        Hessian2Input hessian2Input = new Hessian2Input(new ByteArrayInputStream(bytes));
        hessian2Input.setSerializerFactory(serializerFactory);
        Object resultObject;
        try {
            resultObject = hessian2Input.readObject();
            hessian2Input.close();
            return (T) resultObject;
        } catch (IOException e) {
            throw new CodecException("IOException occurred when Hessian serializer decode!", e);
        }

    }

}
